// Fill out your copyright notice in the Description page of Project Settings.


#include "SnakeGameModeBase.h"
#include "Rock.h"
#include "Food.h"
#include "SpecialFood.h"

ASnakeGameModeBase::ASnakeGameModeBase()
{
	MapSize = 10;
	GameStage = 0;
	IsDead = false;
}

void ASnakeGameModeBase::BeginPlay()
{
	Super::BeginPlay();
	ElementSize = 500.0f / (MapSize + 0.0f);
	FoodLocation = FVector2D(-1000.0f, -1000.0f);
	NextStage();
	for (int i = -MapSize; i <= MapSize + 1; i++)
	{
		GenerateRock(GetCoordinates(FVector2D(i, MapSize + 1)));
		GenerateRock(GetCoordinates(FVector2D(i, -MapSize)));
	}
	for (int i = -MapSize + 1; i <= MapSize; i++)
	{
		GenerateRock(GetCoordinates(FVector2D(MapSize + 1, i)));
		GenerateRock(GetCoordinates(FVector2D(-MapSize, i)));
	}
}

float ASnakeGameModeBase::GetElementSize()
{
	return ElementSize;
}

void ASnakeGameModeBase::GenerateFood(FVector Location)
{
	FActorSpawnParameters SpawnInfo;
	SpawnInfo.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
	float Proportion = ElementSize * 0.01f;
	FTransform CurrentLocation = FTransform(FRotator().ZeroRotator, Location);
	AFood* NewElement = GetWorld()->SpawnActor<AFood>(FoodClass, CurrentLocation, SpawnInfo);
	NewElement->GetRootComponent()->SetWorldScale3D(FVector(Proportion, Proportion, Proportion));
	NewElement->AddActorWorldOffset(FVector(0.0, 0.0, -2000.0f));
	GameStage++;
}

void ASnakeGameModeBase::GenerateSpecialFood(FVector Location)
{
	FActorSpawnParameters SpawnInfo;
	SpawnInfo.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
	float Proportion = ElementSize * 0.01f;
	FTransform CurrentLocation = FTransform(FRotator().ZeroRotator, Location);
	if (IsValid(SpeedupBonusItem))
	{
		SpeedupBonusItem->Destroy();
	}
	ASpecialFood* NewElement = GetWorld()->SpawnActor<ASpecialFood>(SpecialFoodClass, CurrentLocation, SpawnInfo);
	NewElement->GetRootComponent()->SetWorldScale3D(FVector(Proportion, Proportion, Proportion));
	NewElement->AddActorWorldOffset(FVector(0.0, 0.0, -2000.0f));
	SpeedupBonusItem = NewElement;
}

void ASnakeGameModeBase::GenerateRock(FVector Location)
{
	FActorSpawnParameters SpawnInfo;
	SpawnInfo.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
	float Proportion = ElementSize * 0.01f;
	FTransform CurrentLocation = FTransform(FRotator().ZeroRotator, Location);
	ARock* NewElement = GetWorld()->SpawnActor<ARock>(RockClass, CurrentLocation, SpawnInfo);
	NewElement->GetRootComponent()->SetWorldScale3D(FVector(Proportion, Proportion, Proportion));
	NewElement->AddActorWorldOffset(FVector(0.0, 0.0, -2000.0f));
}

void ASnakeGameModeBase::NextStage()
{
	FVector2D LastFoodLocation = GetFreeCell(FVector2D(-1000.0f, -1000.0f), FoodLocation);
	GenerateFood(GetCoordinates(LastFoodLocation));
	if ((GameStage & 7) == 7 && Rocks.Num() < 100)
	{
		FVector2D Rock = GetFreeCell(LastFoodLocation, FoodLocation);
		GenerateRock(GetCoordinates(Rock));
		Rocks.Add(Rock);
	}
	if ((GameStage & 3) == 3)
	{
		GenerateSpecialFood(GetCoordinates(GetFreeCell(LastFoodLocation, FoodLocation)));
	}
	FoodLocation = LastFoodLocation;
}

void ASnakeGameModeBase::FixDeath()
{
	IsDead = true;
}

FVector2D ASnakeGameModeBase::GetFreeCell(FVector2D LastFoodLocation, FVector2D SnakeHeadLocation)
{
	while (true)
	{
		int32 x = FMath::Rand() % (MapSize << 1) - MapSize + 1;
		int32 y = FMath::Rand() % (MapSize << 1) - MapSize + 1;
		FVector2D Location = FVector2D(x, y);
		if (Location != LastFoodLocation && Location != SnakeHeadLocation && Rocks.Find(Location) == -1)
		{
			return Location;
		}
	}
	return FVector2D();
}

FVector ASnakeGameModeBase::GetCoordinates(FVector2D Location)
{
	return FVector((Location.X - 0.5f) * ElementSize, (Location.Y - 0.5f) * ElementSize, 2000.0f);
}
